/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools mkfs main writer
 */

#include "main_writer.h"

#include <cinttypes>
#include <ctime>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>

#include "constant.h"
#include "device_manager.h"
#include "hmfs_common.h"
#include "hmfs_encoding.h"
#include "hmfs_io.h"
#include "hmfs_log.h"
#include "hmfs_quota.h"
#include "mkfs_format.h"
#include "securec.h"

namespace OHOS {
namespace Hmfs {
constexpr uint32_t DEFAULT_DIR_LINKS = 2;

MainAreaWriter::MainAreaWriter(MkfsFormat &mkfs) : mkfs_(mkfs) {}

int32_t MainAreaWriter::Format()
{
    if (PrepareRootInode() != 0) {
        return -1;
    }

    if (PrepareDefaultDentryRoot() != 0) {
        return -1;
    }

    if (WriteRootInode() != 0) {
        return -1;
    }

    if (WriteQfInodes() != 0) {
        return -1;
    }

    if (mkfs_.cfgPara_.features & HMFS_FEATURE_LOST_FOUND) {
        if (WriteLpfInode() != 0) {
            return -1;
        }
    }

    if (DiscardObsoleteDnode() != 0) {
        return -1;
    }

    if (WriteDentryBlock() != 0) {
        return -1;
    }

    return 0;
}

int32_t MainAreaWriter::PrepareRootInode()
{
    CmdConfig &cfgPara = mkfs_.cfgPara_;
    HmfsData &hmfsData = mkfs_.hmfsData_;

    rootInode_ = std::make_unique<NodeOnDisk>();
    NodeData *rootInode = &rootInode_->node;
    (void)memset_s(rootInode, sizeof(NodeOnDisk), 0, sizeof(NodeOnDisk));

    SetLeValue(rootInode->footer.nodeId, hmfsData.rootInode);
    rootInode->footer.inodeNumber = rootInode->footer.nodeId;
    SetLeValue(rootInode->footer.checkPointVersion, 1);
    SetLeValue(rootInode->footer.nextBlockAddr,
        hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_NODE_HOT] * BLOCKS_PER_SEGMENT + 1);

    SetLeValue(rootInode->inode.fileMode,
        S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    SetLeValue(rootInode->inode.linkCount, (hmfsData.lpfInodeId) ? (DEFAULT_DIR_LINKS + 1) : DEFAULT_DIR_LINKS);
    SetLeValue(rootInode->inode.userId, cfgPara.rootUid);
    SetLeValue(rootInode->inode.groupId, cfgPara.rootGid);
    SetLeValue(rootInode->inode.fileSize, HMFS_BLOCK_SIZE);
    SetLeValue(rootInode->inode.blockSize, 2);    // 2 is inode (1) + dentryblock (1)
    SetLeValue(rootInode->inode.accessTime, GetTimeStamp());
    rootInode->inode.accessTimeNsec = 0;
    SetLeValue(rootInode->inode.changeTime, GetTimeStamp());
    rootInode->inode.changeTimeNsec = 0;
    SetLeValue(rootInode->inode.modificationTime, GetTimeStamp());
    rootInode->inode.modificationTimeNsec = 0;
    rootInode->inode.fileVersion = 0;
    rootInode->inode.xattrNodeId = 0;
    rootInode->inode.fileAttributes = 0;
    SetLeValue(rootInode->inode.directoryDepth, 1);
    SetLeValue(rootInode->inode.directoryLevel, DEFAULT_DIR_LEVEL);

    if (cfgPara.features & HMFS_FEATURE_EXTRA_ATTR) {
        rootInode->inode.inlineFlags = static_cast<uint8_t>(HmfsExtType::HMFS_EXTRA_ATTR);
        SetLeValue(rootInode->inode.extraInodeSize, HmfsCommon::GetInstance().CalcExtraIsize());
    }

    if (cfgPara.features & HMFS_FEATURE_PRJQUOTA) {
        SetLeValue(rootInode->inode.projectId, DEFAULT_PROJECT_ID);
    }

    if (cfgPara.features & HMFS_FEATURE_INODE_CRTIME) {
        SetLeValue(rootInode->inode.creationTime, GetTimeStamp());
        rootInode->inode.creationTimeNsec = 0;
    }

    uint32_t dataBlockCount = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_DATA_HOT] * BLOCKS_PER_SEGMENT;
    SetLeValue(rootInode->inode.dataBlocksAddr[HmfsCommon::GetInstance().GetExtraIsize(&rootInode->inode)],
        dataBlockCount);
    return 0;
}

uint64_t MainAreaWriter::GetTimeStamp()
{
    if (mkfs_.cfgPara_.timeStamp == std::numeric_limits<uint32_t>::max()) {
        return time(nullptr);
    } else {
        return mkfs_.cfgPara_.timeStamp;
    }
}

int32_t MainAreaWriter::WriteRootInode()
{
    HmfsData &hmfsData = mkfs_.hmfsData_;

    uint64_t blockId = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_NODE_HOT] * BLOCKS_PER_SEGMENT;

    HMFS_DEBUG("Writing root inode (hot node), 0x%x 0x%x at blockId 0x%" PRIx64 "",
        hmfsData.mainStartBlkId, hmfsData.currentSegments[CURSEG_NODE_HOT], blockId);

    if (HmfsCommon::GetInstance().WriteInode(&rootInode_->node, blockId, hmfsData.checksumSeed) < 0) {
        HMFS_ERROR("failed to write the root inode to disk.");
        return -1;
    }
    return 0;
}

int32_t MainAreaWriter::WriteQfInodes()
{
    CmdConfig &cfgPara = mkfs_.cfgPara_;

    uint32_t i = 0;
    for (int32_t qtype = 0; qtype < MAX_QUOTAS; qtype++) {
        if (!((1 << qtype) & cfgPara.quotaBits)) {
            continue;
        }

        if (WriteQfInode(qtype, i++)) {
            HMFS_ERROR("Failed to write quota inode");
        }
    }

    return 0;
}

int32_t MainAreaWriter::WriteQfInode(int32_t qtype, uint32_t offset)
{
    HmfsData &hmfsData = mkfs_.hmfsData_;
    SuperBlockData *superBlock = mkfs_.GetSuperBlockData();
    if (superBlock == nullptr) {
        return -1;
    }

    auto nodeBuf = std::make_unique<NodeOnDisk>();
    NodeData *qfInode = &nodeBuf->node;
    auto result = memset_s(qfInode, sizeof(NodeOnDisk), 0, sizeof(NodeOnDisk));
    HMFS_CHECK(result == EOK, return -1, "Failed to memset qfInode");

    HmfsCommon::GetInstance().InitQfInode(qfInode, GetLeValue(superBlock->quotaInodeId[qtype]), GetTimeStamp());

    SetLeValue(qfInode->footer.nextBlockAddr,
        hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_NODE_HOT] * BLOCKS_PER_SEGMENT + 1 + qtype + 1);
    SetLeValue(qfInode->inode.blockSize, 1 + QUOTA_DATA_BLOCK_COUNT);

    uint64_t dataBlkId = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_DATA_HOT] * BLOCKS_PER_SEGMENT + 1 +
        offset * QUOTA_DATA_BLOCK_COUNT;
    uint32_t id = qfInode->inode.userId;
    if (qtype == GRP_QUOTA) {
        id = qfInode->inode.groupId;
    } else if (qtype == PROJECT_QUOTA) {
        id = qfInode->inode.projectId;
    }

    if (WriteDefaultQuotaData(qtype, dataBlkId, id) != 0) {
        return -1;
    }

    for (uint32_t i = 0; i < QUOTA_DATA_BLOCK_COUNT; i++) {
        SetLeValue(qfInode->inode.dataBlocksAddr[HmfsCommon::GetInstance().GetExtraIsize(&qfInode->inode) + i],
            dataBlkId + i);
    }

    uint64_t blockId = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_NODE_HOT] * BLOCKS_PER_SEGMENT +
        offset + 1;

    HMFS_DEBUG("Writing quota inode (hot node), 0x%x 0x%x 0x%x at blockId 0x%" PRIx64 ".",
        hmfsData.mainStartBlkId, hmfsData.currentSegments[CURSEG_NODE_HOT], BLOCKS_PER_SEGMENT, blockId);

    if (HmfsCommon::GetInstance().WriteInode(qfInode, blockId, hmfsData.checksumSeed) < 0) {
        HMFS_ERROR("Failed to write the qfInode to disk.");
        return -1;
    }

    hmfsData.quotaInodeCount++;
    return 0;
}

int32_t MainAreaWriter::WriteDefaultQuotaData(int32_t qtype, uint64_t dataBlkId, uint32_t id)
{
    HmfsData &hmfsData = mkfs_.hmfsData_;
    uint32_t bufLen = HMFS_BLOCK_SIZE * QUOTA_DATA_BLOCK_COUNT;
    auto buf = static_cast<uint8_t *>(calloc(sizeof(uint8_t), bufLen));
    if (buf == nullptr) {
        HMFS_ERROR("not enough memory for quota data");
        return -1;
    }

    DiskQuotaHeader *dqHeader = reinterpret_cast<DiskQuotaHeader *>(buf);
    SetLeValue(dqHeader->dqhMagic, INIT_QUOTA_MAGICS[qtype]);
    SetLeValue(dqHeader->dqhVersion, 1);

    DiskQuotaInfo *dqInfo = reinterpret_cast<DiskQuotaInfo *>(dqHeader + 1);
    SetLeValue(dqInfo->dqiBgrace, MAX_DQ_TIME);
    SetLeValue(dqInfo->dqiIgrace, MAX_IQ_TIME);
    dqInfo->dqiFlags = 0;
    SetLeValue(dqInfo->dqiBlocks, QT_TREE_OFFSET + QT_DEFAULT_FREE_ENTRIES);
    dqInfo->dqiFreeBlk = 0;
    SetLeValue(dqInfo->dqiFreeEntry, QT_DEFAULT_FREE_ENTRIES);

    buf[QUOTA_CONTENT_ONE_OFFSET] = QUOTA_CONTENT_ONE_VALUE;
    buf[QUOTA_CONTENT_TWO_OFFSET] = QUOTA_CONTENT_TWO_VALUE;
    buf[QUOTA_CONTENT_THREE_OFFSET] = QUOTA_CONTENT_THREE_VALUE;
    buf[QUOTA_CONTENT_FOUR_OFFSET] = QUOTA_CONTENT_FOUR_VALUE;
    buf[QUOTA_CONTENT_FIVE_OFFSET] = QUOTA_CONTENT_FIVE_VALUE;

    const uint32_t diskQuotaBlockOffset = 5136;
    DiskQuotaBlock *dqBlock = reinterpret_cast<DiskQuotaBlock *>(buf + diskQuotaBlockOffset);
    dqBlock->dqbId = id;
    dqBlock->dqbPad = 0;
    dqBlock->dqbIhardlimit = 0;
    dqBlock->dqbIsoftlimit = 0;
    uint64_t currentInodeCount = (hmfsData.lpfInodeId) ? 2 : 1; // 2 is rootInode(1) + lpfInode(1 or 0)
    SetLeValue(dqBlock->dqbCurinodes, currentInodeCount);
    dqBlock->dqbBhardlimit = 0;
    dqBlock->dqbBsoftlimit = 0;
    SetLeValue(dqBlock->dqbCurspace, currentInodeCount * HMFS_BLOCK_SIZE);
    dqBlock->dqbBtime = 0;
    dqBlock->dqbItime = 0;

    if (HmfsIo::GetInstance().DevWriteBlock(buf, dataBlkId) ||
        HmfsIo::GetInstance().DevWriteBlock(buf + HMFS_BLOCK_SIZE, dataBlkId + 1)) {
        HMFS_ERROR("failed to write quota data block to disk.");
        free(buf);
        return -1;
    }
    HMFS_DEBUG("Writing quota data, at block 0x%" PRIx64 ", 0x%" PRIx64 ".", dataBlkId, dataBlkId + 1);
    free(buf);

    hmfsData.quotaDataBlks += QUOTA_DATA_BLOCK_COUNT;
    return 0;
}

int32_t MainAreaWriter::WriteLpfInode()
{
    HmfsData &hmfsData = mkfs_.hmfsData_;

    auto nodeBuf = std::make_unique<NodeOnDisk>();
    (void)memset_s(nodeBuf.get(), sizeof(NodeOnDisk), 0, sizeof(NodeOnDisk));
    NodeData *lpfInode = &nodeBuf->node;

    if (FillLpfInode(lpfInode) != 0) {
        return -1;
    }

    uint32_t dataBlockId = WriteDefaultLpfDentry();
    if (dataBlockId == 0) {
        HMFS_ERROR("Failed to add default dentries for lost+found");
        return -1;
    }
    SetLeValue(lpfInode->inode.dataBlocksAddr[HmfsCommon::GetInstance().GetExtraIsize(&lpfInode->inode)], dataBlockId);

    uint64_t blockId = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_NODE_HOT] * BLOCKS_PER_SEGMENT +
        hmfsData.quotaInodeCount + 1;

    HMFS_DEBUG("Writing lost+found inode (hot node),"
        "0x%x 0x%x 0x%x at offset 0x%" PRIx64 ".", hmfsData.mainStartBlkId,
        hmfsData.currentSegments[CURSEG_NODE_HOT], BLOCKS_PER_SEGMENT, blockId);
    if (HmfsCommon::GetInstance().WriteInode(lpfInode, blockId, hmfsData.checksumSeed) < 0) {
        HMFS_ERROR("Failed to write the lost+found inode to disk.");
        return -1;
    }

    hmfsData.lpfInodeCount++;
    return 0;
}

int32_t MainAreaWriter::FillLpfInode(NodeData *lpfInode)
{
    HmfsData &hmfsData = mkfs_.hmfsData_;
    CmdConfig &cfgPara = mkfs_.cfgPara_;

    SetLeValue(lpfInode->footer.nodeId, hmfsData.lpfInodeId);
    lpfInode->footer.inodeNumber = lpfInode->footer.nodeId;
    SetLeValue(lpfInode->footer.checkPointVersion, 1);
    SetLeValue(lpfInode->footer.nextBlockAddr, hmfsData.mainStartBlkId +
        hmfsData.currentSegments[CURSEG_NODE_HOT] * BLOCKS_PER_SEGMENT + 1 + hmfsData.quotaInodeCount + 1);
    SetLeValue(lpfInode->inode.fileMode, S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR);
    SetLeValue(lpfInode->inode.linkCount, DEFAULT_DIR_LINKS);
    SetLeValue(lpfInode->inode.userId, cfgPara.rootUid);
    SetLeValue(lpfInode->inode.groupId, cfgPara.rootGid);
    SetLeValue(lpfInode->inode.fileSize, HMFS_BLOCK_SIZE);
    SetLeValue(lpfInode->inode.blockSize, 2); // 2 is inode (1) + dentry (1)
    SetLeValue(lpfInode->inode.accessTime, GetTimeStamp());
    lpfInode->inode.accessTimeNsec = 0;
    SetLeValue(lpfInode->inode.changeTime, GetTimeStamp());
    lpfInode->inode.changeTimeNsec = 0;
    SetLeValue(lpfInode->inode.modificationTime, GetTimeStamp());
    lpfInode->inode.modificationTimeNsec = 0;
    lpfInode->inode.fileVersion = 0;
    lpfInode->inode.xattrNodeId = 0;
    lpfInode->inode.fileAttributes = 0;
    SetLeValue(lpfInode->inode.parentInodeNumber, hmfsData.rootInode);
    SetLeValue(lpfInode->inode.fileNameLength, strlen(LPF_STRING));
    int32_t ret = memcpy_s(lpfInode->inode.fileName, HMFS_NAME_LEN, LPF_STRING, strlen(LPF_STRING));
    HMFS_CHECK(ret == 0, return -1, "Failed to copy fileName");

    SetLeValue(lpfInode->inode.directoryDepth, 1);
    SetLeValue(lpfInode->inode.directoryLevel, DEFAULT_DIR_LEVEL);

    if (cfgPara.features & HMFS_FEATURE_EXTRA_ATTR) {
        lpfInode->inode.inlineFlags = static_cast<uint8_t>(HmfsExtType::HMFS_EXTRA_ATTR);
        SetLeValue(lpfInode->inode.extraInodeSize, HmfsCommon::GetInstance().CalcExtraIsize());
    }

    if (cfgPara.features & HMFS_FEATURE_PRJQUOTA) {
        SetLeValue(lpfInode->inode.projectId, DEFAULT_PROJECT_ID);
    }

    if (cfgPara.features & HMFS_FEATURE_INODE_CRTIME) {
        SetLeValue(lpfInode->inode.creationTime, GetTimeStamp());
        lpfInode->inode.creationTimeNsec = 0;
    }

    if (cfgPara.features & HMFS_FEATURE_COMPRESSION) {
        lpfInode->inode.compressionAlgorithm = 0;
        lpfInode->inode.logClusterSize = 0;
        lpfInode->inode.padding = 0;
    }

    return 0;
}

uint32_t MainAreaWriter::WriteDefaultLpfDentry(void)
{
    HmfsData &hmfsData = mkfs_.hmfsData_;
    auto buf = std::make_unique<DentryBlock>();
    DentryBlock *dentryBlock = buf.get();
    auto result = memset_s(dentryBlock, sizeof(DentryBlock), 0, sizeof(DentryBlock));
    HMFS_CHECK(result == EOK, return -1, "Failed to memset dentryBlock");

    std::vector<const char *> defaultDirList = { ".", ".." };
    for (size_t i = 0; i < defaultDirList.size(); i++) {
        dentryBlock->dentry[i].hashCode = 0;
        SetLeValue(dentryBlock->dentry[i].inodeNumber, (i == 0) ? hmfsData.lpfInodeId : hmfsData.rootInode);
        SetLeValue(dentryBlock->dentry[i].nameLength, strlen(defaultDirList[i]));
        dentryBlock->dentry[i].fileType = static_cast<uint8_t>(HmfsFileType::HMFS_FT_DIR);
        int32_t ret = memcpy_s(dentryBlock->filename[i], HMFS_SLOT_LEN, defaultDirList[i], strlen(defaultDirList[i]));
        HMFS_CHECK(ret == 0, return -1, "Failed to copy fileName");

        HmfsCommon::GetInstance().TestAndSetBitLe(i, dentryBlock->dentryBitmap);
    }

    uint64_t blockId = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_DATA_HOT] * BLOCKS_PER_SEGMENT + 1 +
        hmfsData.quotaDataBlks;
    HMFS_DEBUG("Writing default dentry lost+found, at offset 0x%" PRIx64 ".", blockId);
    if (HmfsIo::GetInstance().DevWriteBlock(dentryBlock, blockId)) {
        HMFS_ERROR("Failed to write lost+found dentry block to disk.");
        return 0;
    }

    hmfsData.lpfDataBlks++;
    return blockId;
}

int32_t MainAreaWriter::DiscardObsoleteDnode()
{
    HmfsData &hmfsData = mkfs_.hmfsData_;
    CmdConfig &cfgPara = mkfs_.cfgPara_;

    if (cfgPara.zonedMode || (cfgPara.features & HMFS_FEATURE_RO)) {
        return 0;
    }

    auto node = std::make_unique<NodeData>();
    uint64_t startInodePos = hmfsData.mainStartBlkId;
    uint64_t lastInodePos = startInodePos + hmfsData.currentSegments[CURSEG_NODE_HOT] * BLOCKS_PER_SEGMENT +
        hmfsData.quotaInodeCount + hmfsData.lpfInodeCount;
    uint64_t endBlockId = hmfsData.mainStartBlkId + hmfsData.segmentCountInMain * BLOCKS_PER_SEGMENT;
    uint64_t blockId = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_NODE_WARM] * BLOCKS_PER_SEGMENT;
    while ((blockId >= hmfsData.mainStartBlkId) && (blockId < endBlockId)) {
        if (HmfsIo::GetInstance().DevReadBlock(node.get(), blockId)) {
            HMFS_ERROR("failed to read block 0x%" PRIx64 " in traversing direct node", blockId);
            return -1;
        }
        uint64_t nextBlockId = GetLeValue(node->footer.nextBlockAddr);

        HMFS_DEBUG("erasing direct node 0x%" PRIx64 "", blockId);
        auto result = memset_s(node.get(), sizeof(NodeData), 0, sizeof(NodeData));
        HMFS_CHECK(result == EOK, return -1, "Failed to memset node");

        if (HmfsIo::GetInstance().DevWriteBlock(node.get(), blockId)) {
            HMFS_ERROR("failed to erase block 0x%" PRIx64 "", blockId);
            return -1;
        }

        if ((nextBlockId >= startInodePos) || (nextBlockId <= lastInodePos)) {
            break;
        }
        blockId = nextBlockId;
    }

    return 0;
}

int32_t MainAreaWriter::PrepareDefaultDentryRoot()
{
    HmfsData &hmfsData = mkfs_.hmfsData_;

    dentryBlk_ = std::make_unique<DentryBlock>();
    DentryBlock *dentryBlk = dentryBlk_.get();
    auto result = memset_s(dentryBlk, sizeof(DentryBlock), 0, sizeof(DentryBlock));
    HMFS_CHECK(result == EOK, return -1, "Failed to memset dentryBlk");
    std::vector<const char *> defaultDirList = { ".", ".." };
    uint32_t index = 0;
    for (size_t i = 0; i < defaultDirList.size(); i++) {
        dentryBlk->dentry[index].hashCode = 0;
        SetLeValue(dentryBlk->dentry[index].inodeNumber, hmfsData.rootInode);
        SetLeValue(dentryBlk->dentry[index].nameLength, strlen(defaultDirList[i]));
        dentryBlk->dentry[index].fileType = static_cast<uint8_t>(HmfsFileType::HMFS_FT_DIR);
        int32_t ret = memcpy_s(dentryBlk->filename[index], HMFS_SLOT_LEN, defaultDirList[i], strlen(defaultDirList[i]));
        HMFS_CHECK(ret == 0, return -1, "Failed to copy fileName");
        HmfsCommon::GetInstance().TestAndSetBitLe(index, dentryBlk->dentryBitmap);
        index++;
    }

    if (hmfsData.lpfInodeId) {
        size_t len = strlen(LPF_STRING);
        uint32_t hash = HmfsCommon::GetInstance().ExecDentryHash(0, 0,
            reinterpret_cast<const unsigned char*>(LPF_STRING), len);

        dentryBlk->dentry[index].hashCode = NativeToLE32(hash);
        dentryBlk->dentry[index].inodeNumber = NativeToLE32(hmfsData.lpfInodeId);
        dentryBlk->dentry[index].nameLength = NativeToLE16(len);
        dentryBlk->dentry[index].fileType = static_cast<uint8_t>(HmfsFileType::HMFS_FT_DIR);
        (void)memcpy_s(dentryBlk->filename[index], HMFS_SLOT_LEN, LPF_STRING, HMFS_SLOT_LEN);
        HmfsCommon::GetInstance().TestAndSetBitLe(index, dentryBlk->dentryBitmap);
        index++;

        int32_t ret = memcpy_s(dentryBlk->filename[index], HMFS_SLOT_LEN, &LPF_STRING[HMFS_SLOT_LEN],
            len - HMFS_SLOT_LEN);
        HMFS_CHECK(ret == 0, return -1, "Failed to copy fileName");
        HmfsCommon::GetInstance().TestAndSetBitLe(index, dentryBlk->dentryBitmap);
    }

    return 0;
}

int32_t MainAreaWriter::WriteDentryBlock()
{
    HmfsData &hmfsData = mkfs_.hmfsData_;

    uint64_t blockId = hmfsData.mainStartBlkId + hmfsData.currentSegments[CURSEG_DATA_HOT] * BLOCKS_PER_SEGMENT;

    HMFS_DEBUG("Writing default dentry root, at offset 0x%" PRIx64 "", blockId);
    if (HmfsIo::GetInstance().DevWriteBlock(dentryBlk_.get(), blockId) < 0) {
        HMFS_ERROR("failed to write the dentry block to disk.");
        return -1;
    }

    return 0;
}

} // namespace Hmfs
} // namespace OHOS
